# Copyright 2010 Michael Penhallegon

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

# http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,

from dj.blog.models import Article, Page
from datetime import datetime, timedelta
from django.db import connection, transaction

class BaseData():
    def retrievedata(self,value,step=None,public=True):
        '''retrieve data about the blog if public is false than will show private
        data and if step is present send it to the function'''
        self.page = Page.objects.filter(name=value)[0]

        #by defualt, retrieves all public article (pub_objects) filters them to the page
        #specified and only ones published before today's date, then 
        #splice that into the last 20 articles
        
        #if the public flag = false then will retrieve all articles that are under that
        #page not published after today
        
        #if all of this fail try to query for all public items
        
        #and if all else fails return a error page
        try:
            if public == True:
                self.article= Article.pub_objects.filter(page=self.page).filter(pub_date__lte=datetime.now())[int(step)*5:(int(step)+1)*5]
            else:
                self.article= Article.objects.filter(page=self.page).filter(pub_date__lte=datetime.now())
        except TypeError:
            if public == True:
                self.article= Article.pub_objects.filter(page=self.page).filter(pub_date__lte=datetime.now())
        except IndexError:
            class ar():
                def __init__(self):
                    self.title = "Error:"
                    self.body = "Query Failed: IndexError"
            self.article= [ar(),]
    def getArticle(self):
        '''retrieves public articles'''
        return self.article
    def getCSS(self):
        '''retrieves the css style'''
        return self.page.themes.order_by('url')
    def getTitle(self):
        '''retrieves the pages title'''
        return self.page.name
    def getLink(self):
        '''retrieves the pages link'''
        return self.page.link
    def getPages(self):
        pages = Page.objects.filter(approved=3)
        return pages
class AboutData(BaseData):
    '''a holder for the About Page'''
    def __init__(self):
        self.page_value = "About"
        self.retrievedata(self.page_value)
    def getArticle(self):
        '''retrieves the articles, modified from basedata since only getting 
        one article'''
        try:
            return self.article[0]
        except:
            return {'title':'Sorry the was a bug','body':'there was a bug we are sorry and we are were quickly to fix it'}
    def getSidebar(self):
        pass
class BlogData(BaseData):
    '''A holder for the Blog Page'''
    def __init__(self, step=None):
        '''init of basedata to set page_value as 'Blog' and init data retrieval'''
        self.page_value = 'Blog'
        self.retrievedata(self.page_value,step)
    def getArticleByDate(self,year,month=0):
        '''retrieves article by date, if the month is left out retrieves only by
        year and if with month retrieves just month'''
        if month > 0:
            archivearticles = Article.pub_objects.filter(page=self.page).filter(pub_date__year = year).filter(pub_date__month = month)
        else:
            archivearticles = Article.pub_objects.filter(page=self.page).filter(pub_date__year = year)
        return archivearticles
    def getArticleBySlug(self,sq):
        '''retrieves the articles slug which is used as a permalink'''
        return self.article.filter(slug=sq)[0]
class SidebarData(BlogData):
    def __init__(self,public=True):
        self.page_value = "blog_sidebar"
        self.retrievedata(self.page_value)
    def retrievedata(self,value,step=None,public=True):
        self.page = Page.objects.filter(name=value)[0]
        if public == True:
            self.article= Article.pub_objects.filter(page=self.page).filter(pub_date__lte=datetime.now())
        else: 
            self.article= Article.objects.filter(page=self.page).filter(pub_date__lte=datetime.now()) 
    def getSidebarDates(self,page):
        '''custom SQL query that gathers all the dates and provides
        links for a sidebar'''
        title = page.getTitle()
        dates = self.sidebarQuery(title)
        s = "\n\n"
        for archdate in dates:
            s += format("* [%s/%d](/%s/articles/%d/%s/)\n\n" %
                (archdate["month_name"],archdate["year"],page.getTitle().lower(),archdate["year"],archdate["month"]))
        #TODO modify/creat archive_act for active version of article
        dd = Article.objects.filter(slug="archives")[0]
        dd.slug = "archives_act"
        dd.body += s
        dd.id += 1
        dd.status = 3
        dd.save()
        self.retrievedata(self.page_value)
        return dates
    def sidebarQuery(self,title):
        ''' selects distinct values of month and date from blog_article
         (the table holding the blog data) making sure only the visible
         articles from the respective request page is displayed
         grouping by year and then month'''


        query = '''SELECT DISTINCT date_part('year',pub_date) as year,date_part('month',pub_date) as month from blog_article 
        where blog_article.status > 2 and 
        blog_article.page_id = 
        (select id from blog_page where blog_page.name = '%s')
        group by year, month''' % (title,)

        # create a traditional sql connection since django with models will not
        # easily let you do group by
        cursor = connection.cursor()
        cursor.execute(query)
        all = cursor.fetchall()

        #create a dictionary to use to get abbreviations for each month
        month = {
                    1:'Jan',
                    2:'Feb',
                    3:'Mar',
                    4:'Apr',
                    5:'May',
                    6:'Jun',
                    7:'Jul',
                    8:'Aug',
                    9:'Sep',
                    10:'Oct',
                    11:'Nov',
                    12:'Dec',
                    }
        #convert the date entry to a year and month combo
        conv_int = lambda x: {'year':int(x[0]),'month':"%02d" % (int(x[1])),'month_name': month[x[1]]}
        # map the lambda function over the dataset
        all_dates = map (conv_int,all)
        return all_dates
